<template>
  <div :style="{ width, height }">
    <component
      :is="componentId"
      :chart="chart"
      @setUpdate="setUpdate"
      @initCallback="initCallback"
      @errCallback="errCallback"
      v-bind="$attrs"
    />
  </div>
</template>
<script>
import { theme } from "@/utils/itcast.js";
import * as echarts from "echarts";
import { useCounterStore } from "@/pinia/modules/bigScreen";
/**
 * 图表基础组件
 * @module echartsVue
 * 业务组件可自行在globalComponent文件夹下面创建
 */
export default {
  name: "CEcharts",
  /**
   *
   * @Members props
   * @description 图表组件传入参数
   * @param {Object} echartsData - 图表数据  xAxisData是X轴的数据项  seriesData是图表展示的数据项
   * @param {String} componentId - 业务组件的名称
   * @param {Boolean} registerTheme - 是否主题切换
   * @param {String} className - 实例的类名
   * @param {String} width - 实例的宽度
   * @param {String} height - 实例的高度
   * @param {String} top - 图表距离上方的位置
   * @param {String} right - 图表距离右方的位置
   * @param {String} bottom - 图表距离下方的位置
   * @param {String} left - 图表距离左方的位置
   * @param {Array} barBorderRadius - 柱状图圆角属性
   * @param {String} barMaxWidth - 柱状图柱子的宽度
   * @param {String} title - 图表的标题名称
   * @param {String} axisLabelColor - x,y轴的字体颜色
   * @param {String} axisLineColor - x,y轴线的颜色
   * @param {String} tooltipBackgroundColor - tooltip的背景颜色
   * @param {String} tooltipFontColor - tooltip的字体颜色
   * @param {Number} rotate - x轴文字倾斜的角度
   * @param {Number} axisLabelMargin - x轴文字距离上方的距离
   * @param {Array} radius - 饼图radius属性
   * @param {Array} center - 饼图center属性
   * @param {Number} fontSize - 字体大小属性
   * @param {Array} colorList - 图表颜色属性
   * @param {Number} lineStyleWidth - 折线图width属性
   * @param {String} roseType - 饼图roseType属性，通过改参数能实现玫瑰图的操作
   * @param {Object} lineStyle - 折现图的样式属性
   * @param {Object} trigger - tooltip的trigger属性
   * @param {Object} tooltip - 自定义tooltip属性
   * @param {Boolean} showLegend - 是否显示legend
   * @param {Object} legend - 自定义legend属性
   */
  props: {
    echartsData: {
      type: Object,
      default: () => {
        return {
          xAxisData: ["张三", "李四", "王五", "老六"],
          seriesData: [
            {
              name: "1",
              value: [100, 30, 1000, 40],
            },
            {
              name: "2",
              value: [400, 600, 10, 40],
            },
          ],
        };
      },
    },
    registerTheme: {
      type: Boolean,
      default: true,
    },
    componentId: {
      type: String,
      default: "",
    },
    className: {
      type: String,
      default: "chart",
    },
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "80%",
    },
    top: {
      type: String,
      default: "15%",
    },
    right: {
      type: String,
      default: "5%",
    },
    left: {
      type: String,
      default: "5%",
    },
    bottom: {
      type: String,
      default: "5%",
    },
    barBorderRadius: {
      type: Array,
      default: () => [7, 7, 0, 0],
    },
    barMaxWidth: {
      type: String,
      default: "20",
    },
    title: {
      type: String,
      default: "",
    },
    axisLabelColor: {
      type: String,
      default: "rgba(255,255,255,1)",
    },
    axisLineColor: {
      type: String,
      default: "rgba(255,255,255,0.6)",
    },
    tooltipBackgroundColor: {
      type: String,
      default: "rgba(0,0,0,.6)",
    },
    tooltipFontColor: {
      type: String,
      default: "#fff",
    },
    rotate: {
      type: Number,
    },
    axisLabelMargin: {
      type: Number,
      default: 10,
    },
    radius: {
      type: Array,
      default: () => ["40%", "70%"],
    },
    center: {
      type: Array,
      default: () => ["50%", "50%"],
    },
    fontSize: {
      type: Number,
      default: 0.75,
    },
    colorList: {
      type: Array,
      default: () => [],
    },
    lineStyleWidth: {
      type: Number,
      default: 3,
    },
    roseType: {
      type: String,
      default: "",
    },
    lineStyle: {
      type: Object,
      default: () => {},
    },
    trigger: {
      type: String,
      default: "",
    },
    tooltip: {
      type: Object,
      default: () => {},
    },
    showLegend: {
      type: Boolean,
      default: false,
    },
    legend: {
      type: Object,
      default: () => {},
    },
    option: {
      type: Object,
      default: null,
    },
  },
  data() {
    return {
      chart: null,
      store: null,
      resizeHandler: null,
    };
  },
  watch: {
    // 监听数据的变化，数据变化图表重新加载
    echartsData(val) {
      this.echartsData = val;
      this.chart = null;
      this.$nextTick(() => {
        this.initChart();
      });
    },
    // 监听主题变化
    "store.echartsTheme"(val) {
      this.initChart();
    },
    option: {
      handler(val) {
        this.initChart();
      },
      deep: true,
    },
    deep: true,
    immediate: true,
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }

    window.removeEventListener("resize", this.resizeHandler);
    this.chart.dispose();
    this.chart = null;
  },
  created() {},
  mounted() {
    this.store = useCounterStore();
    this.resizeHandler = this.debounce(() => {
      if (this.chart) {
        this.chart.resize();
        this.initChart();
      }
    }, 300);
    window.addEventListener("resize", this.resizeHandler);
    this.initChart();
  },
  methods: {
    // 防抖函数
    debounce(func, wait, immediate) {
      let timeout, args, context, timestamp, result;

      const later = function () {
        const last = +new Date() - timestamp;
        if (last < wait && last > 0) {
          timeout = setTimeout(later, wait - last);
        } else {
          timeout = null;
          if (!immediate) {
            result = func.apply(context, args);
            if (!timeout) context = args = null;
          }
        }
      };

      return function () {
        context = this;
        args = arguments;
        timestamp = +new Date();

        if (immediate && !timeout) {
          result = func.apply(context, args);
          context = args = null;
        }

        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        return result;
      };
    },
    initChart() {
      const that = this;
      // 判断实例是否已经存在 存在销毁echarts
      if (this.chart) {
        this.chart.dispose();
      }
      // 主题名称，注册主题是名称不能使用重复的否则切换主题是将不会生效
      const name = "itcast" + new Date().getTime();
      // 注册主题，添加主题可在theme.js中新增变量
      if (this.registerTheme) {
        echarts.registerTheme(name, theme[this.store.echartsTheme]);
      }
      this.chart = echarts.init(this.$el, name);
      // 显示loading效果
      this.chart.showLoading({
        text: "加载中，请稍候...",
        maskColor: "transparent",
        textColor: "#fff600",
      });
    },
    /**
     *
     * @method setUpdate
     * @function setUpdate
     * @description 图表加载完成之后的回调，再次抛出去是为了能在主页面能直接修改option里面的属性
     */
    setUpdate(e) {
      this.chart.hideLoading();
      this.$emit("setUpdate", this.chart);
    },
    /**
     *
     * @method initCallback
     * @function initCallback
     * @description 图表加载之前的回调
     */
    initCallback(option, chart) {
      this.$emit("initCallback", option, chart);
    },
    /**
     *
     * @method errCallback
     * @function errCallback
     * @description 图表加载时报错的回调
     */
    errCallback(err, chart) {
      this.$emit("errCallback", err, chart);
    },
  },
};
</script>
